﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Win32;
using System.Windows;
using System.Xml;
using System.IO;
using System.Windows.Controls;
using SHomeWorkshop.LunarConcept.Tools;
using System.Runtime.Remoting.Messaging;

namespace SHomeWorkshop.LunarConcept.Commands
{
    /// <summary>
    /// 创建时间：2011年12月28日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：打开文档命令。此命令总是处于“可用”状态。
    /// ★★说明：关于自定义命令的实现，可参考“NewDocument”类的备注。
    /// </summary>
    public static class OpenDocumentCommand
    {

        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态][构造方法]
        /// 
        /// ——此方法会初始化并向WPF系统注册一个RoutedUICommand。
        /// </summary>
        static OpenDocumentCommand()//类型构造器
        {
            routedUICmd = new RoutedUICommand(
                "OpenDocumentCommand",
                "OpenDocumentCommand",
                typeof(OpenDocumentCommand),//创建RoutedUICommand对象
                null);

            routedUICmd.InputGestures.Add(new KeyGesture(Key.O, ModifierKeys.Control, "Ctrl + O"));

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        #endregion

        #region 字段与属性===================================================================================================

        private static CommandBinding cmdBinding = new CommandBinding();
        /// <summary>
        /// 用在主窗口CommandBindings集合中的命令绑定。
        /// 
        /// 它的Command是RoutedUICommand。
        /// ——因此，RoutedUICommand是否可以运行将由CmdBinding的CanExecute事件决定。
        /// ——而且，RoutedUICommand的执行也是通过CmdBinding的Execute事件来进行的。
        /// </summary>
        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        private static RoutedUICommand routedUICmd;
        /// <summary>
        /// [只读静态属性]表示在WPF系统中注册的一个RoutedUICommand。
        /// ——必须和CommandBinding配合才能使用。
        ///     CommandBinding要添加到主窗口的CommandBindings集合中；
        ///     RoutedUICommand则要向WPF系统注册。
        ///     
        /// ★说明：使用静态属性是因为这样在Xaml代码中比较便于绑定。
        /// </summary>
        public static RoutedUICommand RoutedUICmd
        {
            get { return routedUICmd; }
        }

        #endregion

        #region 方法=========================================================================================================

        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;//打开文档，此命令总是有效。
        }

        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (Globals.MainWindow.EditorManager.IsModified)
            {
                MessageBoxResult result = MessageBox.Show("　　当前文档已被修改，是否需要保存？",
                    Globals.AppName, MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
                switch (result)
                {
                    case MessageBoxResult.Yes:
                        {
                            string saveResult = SaveDocumentCommand.Execute();

                            if (saveResult == Commands.SaveDocumentCommand.CancelSaveMessage)
                            {
                                return;
                            }
                            else if (saveResult != string.Empty)
                            {
                                MessageBox.Show("　　打开新文档前无法保存当前文档。异常信息如下：\r\n" + result,
                                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                                return;
                            }

                            break;
                        }
                    case MessageBoxResult.No:
                        {
                            break;
                        }
                    case MessageBoxResult.Cancel:
                        {
                            return;
                        }
                    default: break;
                }
            }

            Execute();
        }

        public static string Execute(string filePath = null)
        {
            if (Globals.CmdParameterString != null)
            {
                if (Globals.CmdParameterString.EndsWith("." + Globals.ExtensionNameOfTemplate) ||
                    Globals.CmdParameterString.EndsWith(".png"))
                {
                    string result = ReadOutportedPNGImageFile(Globals.CmdParameterString);
                    if (result != string.Empty)
                    {
                        Globals.MainWindow.EditorManager.InitilizeDocument();
                        Globals.CmdParameterString = null;
                        //这种情况极为罕见，通常只有用户从命令行手工调用才会出现这个问题。
                        return result;
                    }
                }
                else
                {
                    string result = ReadDocumentFromDiskFile(Globals.CmdParameterString);
                    if (result != string.Empty)
                    {
                        Globals.MainWindow.EditorManager.InitilizeDocument();
                        Globals.CmdParameterString = null;
                        //这种情况极为罕见，通常只有用户从命令行手工调用才会出现这个问题。
                        return result;
                    }
                }

                //Globals.MainWindow.InvalidateArrange();
                //Globals.MainWindow.UpdateLayout();

                Globals.MainWindow.EditorManager.FullPathOfDiskFile = Globals.CmdParameterString;
                Globals.MainWindow.EditorManager.Build();
                Globals.MainWindow.EditorManager.ModifingItemsList.Reset();

                RecentFileItem.WriteRecentFilesToXmlFile(Globals.CmdParameterString);
                RecentFileItem.ReadRecentFilesFromXmlFile();
                Globals.MainWindow.Activate();

                Globals.CmdParameterString = null;//这个只在程序启动时执行一次。

                return string.Empty;
            }

            if (filePath == null)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Title = Globals.AppName + "——打开文档：";
                ofd.Filter = Globals.DocumentName + "(*." + Globals.ExtensionName + ")|*." +
                    Globals.ExtensionName + "|" +
                    Globals.DocumentName + "模板|*." + Globals.ExtensionNameOfTemplate +
                    "|Png 导出图(*.png)|*.png";
                ofd.FilterIndex = 0;
                ofd.Multiselect = false;

                if (ofd.ShowDialog() != true)
                {
                    Globals.MainWindow.MainScrollViewer.Focus();
                    return string.Empty;//用户取消操作，视为成功执行，不需要返回错误信息。
                }

                filePath = ofd.FileName;
            }

            Globals.MainWindow.EditorManager.CloseDocument();//“关闭”文档，其实是重置文档默认属性。

            if (filePath.EndsWith("." + Globals.ExtensionNameOfOutportPng) ||
                filePath.EndsWith("." + Globals.ExtensionNameOfTemplate))//模板文件本质上也是png文件（为支持预览）。
            {
                //本程序导出的png格式的图片末尾附带了整个文档的Xml数据。
                string result = ReadOutportedPNGImageFile(filePath);
                if (result == string.Empty)
                {
                    Globals.MainWindow.EditorManager.FullPathOfDiskFile = filePath;
                }
                else return result;
            }
            else
            {
                string result = ReadDocumentFromDiskFile(filePath);
                if (result == string.Empty)
                {
                    Globals.MainWindow.EditorManager.FullPathOfDiskFile = filePath;
                }
                else return result;
            }

            Globals.MainWindow.EditorManager.Build();

            foreach (var pe in Globals.MainWindow.EditorManager.GetAllPageEditors())
            {
                var widgets = pe.GetAllWidgets();
                foreach (var widget in widgets)
                {
                    var cw = widget as Widgets.ContentWidget;
                    if (cw == null) continue;

                    cw.RefreshTextRotateAngle();
                    cw.InvalidateVisual();

                    var gw = cw as Widgets.GroupWidget;
                    if(gw != null)
                    {
                        Widgets.GroupWidget.ReDrawSubLineWidgets(gw);
                    }
                }
            }

            Globals.MainWindow.EditorManager.ModifingItemsList.Reset();

            RecentFileItem.WriteRecentFilesToXmlFile(filePath);
            RecentFileItem.ReadRecentFilesFromXmlFile();

            //Globals.MainWindow.EditorManager.RefreshPaginations();//Build方法中已调用。
            Globals.MainWindow.MainScrollViewer.Focus();

            return string.Empty;
        }

        /// <summary>
        /// 打开曾经导出过的png文档（在png图像文件末尾附加了xml的文档数据）。
        /// ——这个会生成部件。
        /// </summary>
        /// <param name="filename">png文档的路径。</param>
        public static string ReadOutportedPNGImageFile(string filename)
        {
            //XmlReader reader = null;
            //XmlReaderSettings settings = new XmlReaderSettings();
            //settings.ConformanceLevel = ConformanceLevel.Document;
            //settings.IgnoreWhitespace = true;
            //settings.IgnoreComments = true;
            //reader = XmlReader.Create(/*"file:///" +加这个会出错！！！*/ filename, settings);

            bool start = false;
            StringBuilder sb = new StringBuilder();
            using (StreamReader sr = File.OpenText(filename))
            {
                string s = "";
                while ((s = sr.ReadLine()) != null)
                {
                    if (start == false)
                    {
                        if (s.EndsWith(Globals.OutportImageSplitText))
                        {
                            start = true;
                        }

                        continue;
                    }

                    sb.Append(s);
                }

                if (sb.Length <= 0)
                {
                    return "　　这个PNG文件可能不是由本程序导出的图片文件！无法从中获取文档内容。";
                }

                try
                {
                    Globals.MainWindow.EditorManager.XmlDocument.LoadXml(sb.ToString());
                    Globals.MainWindow.EditorManager.Build();
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }

                return string.Empty;
            }
        }

        /// <summary>
        /// 读入Xml文档的文本（但不会创建部件）。
        /// </summary>
        /// <param name="fullFilePath">文件路径。</param>
        public static string ReadDocumentFromDiskFile(string fullFilePath)
        {
            if (fullFilePath == null) return "　　提供的文件路径为null。";
            if (fullFilePath.Length <= 0) return "　　提供的文件路径长度为０。";
            if (System.IO.File.Exists(fullFilePath) != true)
                return string.Format("　　未找到文件：{0}", fullFilePath);

            try
            {
                using (System.Xml.XmlReader reader = new System.Xml.XmlTextReader(/*"file:///" +加这个会出错！！*/ fullFilePath))
                {
                    Globals.MainWindow.EditorManager.XmlDocument.Load(reader);

                    if (Globals.MainWindow.EditorManager.XmlDocument == null ||
                        Globals.MainWindow.EditorManager.XmlDocument.DocumentElement == null ||
                        Globals.MainWindow.EditorManager.XmlDocument.DocumentElement.Name != XmlTags.DocTag)
                    {
                        return "　　这个文件可能不是由本程序生成的文件！无法从中获取文档内容。";
                    }

                    if (Globals.MainWindow.EditorManager.XmlDocument.DocumentElement.SelectSingleNode(XmlTags.PageSetTag) == null)
                    {
                        return "　　这个文件可能不是由本程序生成的文件！无法从中获取文档内容。";
                    }
                }

                return string.Empty;
            }
            catch (Exception ex)
            {
                return "读取文件时发生意外。异常信息如下：\r\n" +
                    ex.Message + "\r\n" + ex.StackTrace;
            }
        }

        #endregion
    }
}
